﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using C1.Win.Chart;
using System.Drawing.Drawing2D;
using C1.Chart;
using System.IO;

namespace FlexChartExplorer.Samples
{
    public partial class Zoom : UserControl
    {
        bool zooming = false;
        Point ptStart = Point.Empty;
        Point ptLast = Point.Empty;

        public Zoom()
        {
            InitializeComponent();
            InitializeControls();

            SetupChart();
        }

        void SetupChart()
        {
            // Create chart with two series

            flexChart1.BeginUpdate();

            flexChart1.Series.Clear();

            // Add sample data
            Series function1 = new Series()
            {
                Name = "Function 1",
                DataSource = DataCreator.Create(x => 2 * Math.Sin(0.16 * x), y => 2 * Math.Cos(0.12 * y), 160),
                Binding = "YVals",
                BindingX = "XVals"
            };
            flexChart1.Series.Add(function1);

            Series function2 = new Series()
            {
                Name = "Function 2",
                DataSource = DataCreator.Create(x => Math.Sin(0.1 * x), y => Math.Cos(0.15 * y), 160),
                Binding = "YVals",
                BindingX = "XVals"
            };
            flexChart1.Series.Add(function2);

            flexChart1.ChartType = C1.Chart.ChartType.LineSymbols;

            flexChart1.ToolTip.Content = "";

            flexChart1.EndUpdate();
        }

        private void PerformZoom(Point ptStart, Point ptLast)
        {
            // Convert points to data coordinates
            var p1 = flexChart1.PointToData(ptStart);
            var p2 = flexChart1.PointToData(ptLast);

            flexChart1.BeginUpdate();

            // Update axes with new limits
            flexChart1.AxisX.Min = Math.Min(p1.X, p2.X);
            flexChart1.AxisY.Min = Math.Min(p1.Y, p2.Y);
            flexChart1.AxisX.Max = Math.Max(p1.X, p2.X);
            flexChart1.AxisY.Max = Math.Max(p1.Y, p2.Y);

            flexChart1.EndUpdate();
        }

        public void ChartMouseDown(Object sender, MouseEventArgs e)
        {
            // Start zooming
            zooming = true;

            // Save starting point of selection rectangle
            ptStart.X = e.X;
            ptStart.Y = e.Y;

            ptLast = Point.Empty;
        }

        public void ChartMouseMove(Object sender, MouseEventArgs e)
        {
            // When zooming update selection range
            if (zooming)
            {
                Point ptCurrent = new Point(e.X, e.Y);

                // Undraw old frame
                if (!ptLast.IsEmpty)
                    DrawReversibleRectangle(ptStart, ptLast);

                // Update last point
                ptLast = ptCurrent;
                // Draw new frame
                DrawReversibleRectangle(ptStart, ptCurrent);
            }
        }

        public void ChartMouseUp(Object sender, MouseEventArgs e)
        {
            // End zooming
            zooming = false;

            // Redraw frame to restore screen 
            if (!ptLast.IsEmpty)
            {
                Point ptCurrent = new Point(e.X, e.Y);
                DrawReversibleRectangle(ptStart, ptLast);
            }

            PerformZoom(ptStart, ptLast);

            // Clean up
            ptStart = ptLast = Point.Empty;
        }

        // Convert and normalize the points and draw the reversible frame
        private void DrawReversibleRectangle(Point p1, Point p2)
        {
            // Convert the points to screen coordinates
            p1 = flexChart1.PointToScreen(p1);
            p2 = flexChart1.PointToScreen(p2);

            // Normalize the rectangle
            var rc = new Rectangle(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y),
                Math.Abs(p2.X - p1.X), Math.Abs(p2.Y - p1.Y));

            // Draw the reversible frame
            ControlPaint.DrawReversibleFrame(rc, Color.DarkRed, FrameStyle.Dashed);
        }

        private void btnResetZoom_Click(object sender, EventArgs e)
        {
            flexChart1.BeginUpdate();

            // Restore default values for axis limits
            flexChart1.AxisX.Min = Double.NaN;
            flexChart1.AxisY.Min = Double.NaN;
            flexChart1.AxisX.Max = Double.NaN;
            flexChart1.AxisY.Max = Double.NaN;

            flexChart1.EndUpdate();
        }

        private void InitializeControls()
        {
            #region Init controls

            flexChart1 = baseSample1.flexChart1;
            baseSample1.flexChart1.MouseDown += ChartMouseDown;
            baseSample1.flexChart1.MouseMove += ChartMouseMove;
            baseSample1.flexChart1.MouseUp += ChartMouseUp;

            baseSample1.lblTitle.Text = Localizer.GetItem("zoom", "title");
            baseSample1.tbDescription.Rtf = Localizer.GetItem("zoom", "description").MakeRtf();

            var btnResetZoom = new Button()
            {
                Text = "Reset Zoom",
                Width = 100,
                FlatStyle = FlatStyle.Flat,
                AutoSize = true
            };
            btnResetZoom.FlatAppearance.BorderColor = System.Drawing.Color.LightGray;
            btnResetZoom.Click += btnResetZoom_Click;
            baseSample1.pControls.Controls.Add(btnResetZoom);

            #endregion
        }
    }
}
